package com.flyxiaozhu.erp.admin.controllers;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.flyxiaozhu.erp.admin.authorize.AuthorizeHelper;
import com.flyxiaozhu.erp.admin.resps.SchemaResp;
import com.flyxiaozhu.erp.core.entities.*;
import com.flyxiaozhu.erp.core.helper.DateHelper;
import com.flyxiaozhu.erp.core.libs.*;
import com.flyxiaozhu.erp.core.repositories.AppRepository;
import com.flyxiaozhu.erp.core.repositories.GoodsOrderDetailRepository;
import com.flyxiaozhu.erp.core.repositories.GoodsOrderRepository;
import com.flyxiaozhu.erp.core.services.GoodsOrderService;
import com.flyxiaozhu.erp.core.services.GoodsService;
import com.flyxiaozhu.erp.core.services.GoodsSkuService;
import com.flyxiaozhu.erp.core.utils.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.security.access.annotation.Secured;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;

/**
 * @author flyxiaozhu
 * @date 2019-04-26 23:27
 */
@RestController
public class OrderController {
    @Autowired
    GoodsOrderRepository goodsOrderRepository;
    @Autowired
    GoodsOrderDetailRepository goodsOrderDetailRepository;
    @Autowired
    GoodsOrderService goodsOrderService;
    @Autowired
    AppRepository appRepository;
    @Autowired
    GoodsService goodsService;
    @Autowired
    GoodsSkuService goodsSkuService;

    @Secured("ROLE_ORDER_SELECT")
    @RequestMapping(value = "/order/select")
    public JSONResult newGetOrderList(HttpServletRequest request, @PageableDefault(sort = {"createTime"}, direction = Sort.Direction.DESC) Pageable pageable) {
        SearchSpecification<GoodsOrder> searchSpecification = new SearchSpecification<>(request);

        searchSpecification.setFilter("search_like_name", (list, field, operator, value, root, query, cb) -> {
                    List<GoodsOrderDetail> details = goodsOrderDetailRepository.findByGoodsNameLike(("%" + value + "%"));
                    if (details.size() != 0) {
                        List<Long> orderIds = CollectionUtils.map(details, GoodsOrderDetail::getOrderId);
                        return cb.in(root.get("id")).value(orderIds);
                    }
                    return cb.equal(root.get("id"), 0);
                }
        );

        Page<GoodsOrder> orders = goodsOrderRepository.findAll(searchSpecification, pageable);

        if (orders.getContent().size() == 0) {
            return new JSONResult().put("list", new ArrayList<>());
        }

        Map<Long, List<GoodsOrderDetail>> orderDetailMap = goodsOrderService.findByOrderIdGroup();
        for (GoodsOrder order : orders.getContent()) {
            order.setDetails(orderDetailMap.get(order.getId()));
        }

        return new JSONResult(orders, pageable.getPageNumber());
    }

    /**
     * 获取配置信息
     *
     * @return
     */
    @RequestMapping(value = "/order/schema")
    public JSONResult schema() {
        List<SchemaResp> querySchema = new ArrayList<>();

        // 商品标签
        SchemaResp appObj = new SchemaResp();

        List<App> appList = appRepository.findAll();
        List<Map> options1 = new ArrayList<>();
        for (App app : appList) {
            Map<String, Object> item = new HashMap<>();
            item.put("key", app.getId());
            item.put("value", app.getName());
            options1.add(item);
        }

        appObj.setKey("search_eq_appId");
        appObj.setTitle("应用");
        appObj.setDataType("varchar");
        appObj.setShowType("select");
        appObj.setOptions(options1);

        querySchema.add(appObj);

        return new JSONResult().put("querySchema", querySchema);
    }

    /**
     * 管理员备注
     *
     * @param id
     * @param remark
     * @return
     */
    @RequestMapping(value = "/order/remark")
    public JSONResult remark(long id, String remark) {
        GoodsOrder order = goodsOrderService.findById(id);
        if (order == null) {
            return new JSONResult(ErrorCode.NO_DATA, "错误的订单ID");
        }

        order.setAdminRemark(remark);
        goodsOrderRepository.save(order);
        return new JSONResult();
    }

    /**
     * 订单关闭
     *
     * @param id
     * @return
     */
    @Secured("ROLE_ORDER_CLOSE")
    @RequestMapping(value = "/order/close")
    @Transactional(rollbackFor = Exception.class)
    public JSONResult close(@RequestParam Long id) {
        GoodsOrder order = goodsOrderService.findById(id);
        if (order == null) {
            return new JSONResult(ErrorCode.INVALID_PARAM, "订单不存在");
        }
        if (order.getStatus() != Constants.ORDER_STATUS_DELIVERY) {
            return new JSONResult(ErrorCode.INVALID_PARAM, "订单状态错误");
        }

        order.setStatus(Constants.ORDER_STATUS_CLOSED);
        order.setCloseTime(DateHelper.getStringDate());
        goodsOrderRepository.save(order);

        List<GoodsOrderDetail> detailList = goodsOrderDetailRepository.findByOrderId(order.getId());
        for (GoodsOrderDetail detail : detailList) {
            //已发货、已完成、已锁定库存
            if (detail.getDeliveryStatus() == Constants.DELIVERY_STATUS_SENT
                    || detail.getDeliveryStatus() == Constants.DELIVERY_STATUS_COMPLETED
                    || detail.getDeliveryStatus() == Constants.DELIVERY_STATUS_LOCKED) {
                Goods goods = goodsService.findById(detail.getGoodsId());
                if (goods != null) {
                    GoodsSku sku = null;
                    if (detail.getSkuId() != 0) {
                        sku = goodsSkuService.findById(detail.getSkuId());
                    }
                    try {
                        StockFactory.getRuleInstance(goods.getRuleId())
                                .refund(order, detail, goods, sku, null);
                    } catch (AppException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        return new JSONResult().put("order", order);
    }

    /**
     * 获取订单详情
     *
     * @param id
     * @return
     */
    @Secured("ROLE_ORDER_DETAILS")
    @RequestMapping(value = "/order/details")
    public JSONResult getOrderDetails(@RequestParam long id) {
        GoodsOrder order = goodsOrderService.findById(id);
        if (order == null) {
            return new JSONResult(ErrorCode.NO_DATA, "订单ID错误");
        }

        List<GoodsOrderDetail> details = goodsOrderDetailRepository.findByOrderId(order.getId());
        order.setDetails(details);

        return new JSONResult().put("order", order);
    }

    /**
     * 发货
     *
     * @return
     */
    @RequestMapping(value = "/order/delivery")
    @Secured("ROLE_ORDER_DELIVERY")
    @SuppressWarnings("unchecked")
    @Transactional(rollbackFor = Exception.class)
    public JSONResult delivery(@RequestParam String body) {
        try {
            Map<String, Object> params = new ObjectMapper().readValue(body, HashMap.class);

            GoodsOrder order = goodsOrderRepository.findById(Long.valueOf((Integer) params.get("id"))).orElse(null);
            if (order == null) {
                return new JSONResult(ErrorCode.NO_DATA, "订单ID错误");
            }

            List<GoodsOrderDetail> details = goodsOrderDetailRepository.findByOrderId(order.getId());
            Map<Long, GoodsOrderDetail> detailMap = CollectionUtils.columnMap(details, GoodsOrderDetail::getId);

            List<Map<String, Object>> eventsData = new ArrayList<>();

            //更新订单详情
            List<Map<String, Object>> changed = (List<Map<String, Object>>) params.get("changed");
            for (Map<String, Object> item : changed) {
                GoodsOrderDetail detail = detailMap.get(Long.valueOf((Integer) item.get("detailId")));
                if (detail == null) {
                    continue;
                }
                if (item.get("expressCode").equals("")) {
                    detail.setExpressCode("");
                    detail.setExpressNo("");
                    detail.setDeliveryStatus(Constants.DELIVERY_STATUS_NORMAL);
                } else {
                    detail.setExpressCode((String) item.get("expressCode"));
                    detail.setExpressNo((String) item.get("expressNo"));
                    detail.setDeliveryStatus(Constants.DELIVERY_STATUS_SENT);
                }

                Map<String, Object> eventData = new HashMap<>();
                eventData.put("expressCode", detail.getExpressCode());
                eventData.put("expressNo", detail.getExpressNo());
                eventData.put("goodsId", detail.getGoodsId());
                eventData.put("skuId", detail.getSkuId());
                eventsData.add(eventData);

                goodsOrderDetailRepository.save(detail);
            }

            AdminUser user = AuthorizeHelper.getUser();

            //记录日志
            List<GoodsOrderDeliveryLog> orderDeliveryLogs = new ArrayList<>();

            GoodsOrderDeliveryLog log = new GoodsOrderDeliveryLog();
            log.setUid(user.getId());
            log.setRealname(user.getRealname());
            log.setChangedData(body);
            log.setRemark((String) params.get("remark"));
            orderDeliveryLogs.add(log);

            order.getDeliveryLogs().addAll(orderDeliveryLogs);

            if (CollectionUtils.every(details, o -> o.getDeliveryStatus() == Constants.DELIVERY_STATUS_SENT || o.getDeliveryStatus() == Constants.DELIVERY_STATUS_COMPLETED)) {
                order.setStatus(Constants.ORDER_STATUS_SENT);
                goodsOrderRepository.save(order);
            }

            order.setDetails(details);
            return new JSONResult().put("order", order);
        } catch (IOException e) {
            return new JSONResult(ErrorCode.INVALID_PARAM, "发货数据错误");
        }
    }
}
